import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//import static com.sun.javaws.jnl.XMLFormat.process;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86183
 * Date: 2023-03-11
 * Time: 21:00
 */
public class TcpEchoServer {
    private ServerSocket serverSocket = null;
    public TcpEchoServer(int port) throws IOException{
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("启动服务器");
        //此时使用CachedThreadPool,使用FixedThreadPool不太合适(线程数不太应该是固定的)
        ExecutorService theadPool = Executors.newCachedThreadPool();
        while (true){
            //使用这个clientSocket 和具体的客户端进行交流
            Socket clientSocket = serverSocket.accept();
            //此处使用多线程来处理
            //使用线程池
            theadPool.submit(()->{
                processConnection(clientSocket);
            });

        }
    }
    //使用这个方法来处理一个连接
    //这一个连接对应到一个客户端,但是这可能会涉及到多次交互
    private void processConnection(Socket clientSocket) {
        System.out.printf("[%s : %d] 客户端上线 !\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
       //基于上述socket对象和客户端进行通信
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()) {
           //由于要处理多个请求和响应,也是使用循环来进行
            while (true) {
                //1.读取请求
               Scanner scanner = new Scanner(inputStream);
               if(!scanner.hasNext()){
                   //没有下个数据,说明读完了(客户端)
                   System.out.printf("[%s : %d] 客户端下线!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                   break;
               }
               //注意 此处使用next是一直读取到换行符/空格/其他空白符结束,但是最终返回结果不包含上述 空白符

               String request = scanner.next();
               //2.根据请求来构造响应
               String reponse = process(request);
               //3.返回响应结果
                // OutputStream 没有write String这样的功能,可以把String里的字节数组拿出来,进行写入
               PrintWriter printWriter = new PrintWriter(outputStream);
               //此处使用println来写入,让结果中带有一个\n换行,方便对端来接收jiexi
               printWriter.println(reponse);
               //flush用来刷新缓冲区,保证当前写入的数据,确实是发送出去了
               printWriter.flush();

               System.out.printf("[%s : %d] req :%s; resp: %s\n",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,reponse);
               
           }
       }catch (IOException e){
           e.printStackTrace();
       }finally {
           try {
               clientSocket.close();
           }catch (IOException e){
               e.printStackTrace();
           }
       }
    }

    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9098);
        server.start();
    }
}
